package com.kuizii.generator.util.generator;

import com.kuizii.generator.util.DateUtils;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * 生成starter模块
 * </p>
 *
 * @author nuanyang
 * Email
 * created by 2018/6/20
 */
public class GenteratorStarterUtils {

    /**
     * 获取模板
     *
     * @return
     */
    private static List<String> getTemplates() {
        List<String> templates = new ArrayList<>();
        templates.add("templates/starter/SpringBootApplication.java.vm");
        templates.add("templates/starter/resources/application.yml.vm");
        templates.add("templates/starter/resources/application-dev.yml.vm");
        templates.add("templates/starter/resources/application-prod.yml.vm");
        templates.add("templates/starter/resources/application-test.yml.vm");
        templates.add("templates/starter/resources/bootstrap.yml.vm");
        templates.add("templates/starter/resources/logback.xml.vm");
        templates.add("templates/starter/pom/starterpom.xml.vm");
        templates.add("templates/banner.txt");
        if ("dubbo".equals(GeneratorConfig.getConfig().getString("rpc-type"))) {
            templates.add("templates/core/config/DubboDocConfig.java.vm");
        }


        return templates;
    }


    /**
     * 生成代码
     */
    public static void generatorCode(ZipOutputStream zip) {
        Configuration config = GeneratorConfig.getConfig();
        //设置velocity资源加载器artifactIdParent
        Properties prop = new Properties();
        prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        Velocity.init(prop);
        //封装模板数据
        Map<String, Object> map = new HashMap<>();
        map.put("author", config.getString("author"));
        map.put("email", config.getString("email"));
        map.put("datetime", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
        map.put("springBootName", columnToJava(GeneratorConfig.getModuleName().replace("-", "_")) +
                WordUtils.capitalize(GeneratorConfig.MODULE_STARTER));
        map.put("artifactId", GeneratorConfig.getProjectNameNotSlash(GeneratorConfig.MODULE_STARTER));
        map.put("description", config.getString("description"));
        map.put("version", config.getString("version"));
        map.put("server-port", config.getString("server-port"));
        map.put("context-path", config.getString("context-path"));
        map.put("sql-url", config.getString("sql-url"));
        map.put("sql-port", config.getString("sql-port"));
        map.put("sql-username", config.getString("sql-username"));
        map.put("sql-password", config.getString("sql-password"));
        map.put("sql-db", config.getString("sql-db"));
        map.put("artifactIdParent", GeneratorConfig.getProjectNameNotSlash(GeneratorConfig.MODULE_CORE));
        map.put("moduleType", GeneratorConfig.MODULE_STARTER);
        map.put("basePackages", config.getString("package") + "." + GeneratorConfig.getModuleName().replace("-", ".") + "." + GeneratorConfig.MODULE_CORE);
        map.put("serverStarterPort", config.getString("serverStarterPort"));
        map.put("applicationName", GeneratorConfig.getProjectName());
        map.put("package", config.getString("package"));
        map.put("moduleName", GeneratorConfig.getModuleName().replace("-", "."));
        map.put("parentArtifactId", GeneratorConfig.getModuleParent() + GeneratorConfig.getModuleName());
        map.put("moduleBizType", GeneratorConfig.MODULE_CORE);
        map.put("coreArtifactId", GeneratorConfig.getModuleParent() + GeneratorConfig.getModulePrefix() + GeneratorConfig.MODULE_CORE);
        //传入sql type
        map.put("sql-type", config.getString("sql-type"));
        map.put("rpc-type", config.getString("rpc-type"));
        VelocityContext context = new VelocityContext(map);
        for (String template : getTemplates()) {
            StringWriter writer = new StringWriter();
            Template tpl = Velocity.getTemplate(template, "UTF-8");
            tpl.merge(context, writer);
            try {
                zip.putNextEntry(new ZipEntry(Objects.requireNonNull(getFileName(template))));
                IOUtils.write(writer.toString(), zip, "UTF-8");
                IOUtils.closeQuietly(writer);
                zip.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取模板名称
     *
     * @param template
     * @return
     */
    private static String getFileName(String template) {
        if (template.contains("SpringBootApplication.java.vm")) {
            return GeneratorConfig.getSpringBootRoute(GeneratorConfig.MODULE_STARTER) +
                    columnToJava(GeneratorConfig.getModuleName().replace("-", "_")) +
                    WordUtils.capitalize(GeneratorConfig.MODULE_STARTER) + "Application.java";
        }

        if (template.contains("application.yml.vm")) {
            return GeneratorConfig.getProjectResourcesRoute(GeneratorConfig.MODULE_STARTER) + "application.yml";
        }
        if (template.contains("application-dev.yml.vm")) {
            return GeneratorConfig.getProjectResourcesRoute(GeneratorConfig.MODULE_STARTER) + "application-dev.yml";
        }
        if (template.contains("application-prod.yml.vm")) {
            return GeneratorConfig.getProjectResourcesRoute(GeneratorConfig.MODULE_STARTER) + "application-prod.yml";
        }
        if (template.contains("application-test.yml.vm")) {
            return GeneratorConfig.getProjectResourcesRoute(GeneratorConfig.MODULE_STARTER) + "application-test.yml";
        }
        if (template.contains("bootstrap.yml.vm")) {
            return GeneratorConfig.getProjectResourcesRoute(GeneratorConfig.MODULE_STARTER) + "bootstrap.yml";
        }
        if (template.contains("starterpom.xml.vm")) {
            return GeneratorConfig.getProjectName(GeneratorConfig.MODULE_STARTER) + "pom.xml";
        }
        if (template.contains("logback.xml.vm")) {
            return GeneratorConfig.getProjectResourcesRoute(GeneratorConfig.MODULE_STARTER) + "logback.xml";
        }
        if (template.contains("banner.txt")) {
            return GeneratorConfig.getProjectResourcesRoute(GeneratorConfig.MODULE_STARTER) + "banner.txt";
        }
        if (template.contains("SpringBootApplicationTests.java.vm")) {
            return GeneratorConfig.getTestApplicationRoute(GeneratorConfig.MODULE_STARTER) + columnToJava(GeneratorConfig.getModuleName().replace("-", "_"))
                    + WordUtils.capitalize(GeneratorConfig.MODULE_STARTER) + "ApplicationTests.java";
        }
        if (template.contains("bootstrap-prod.yml.vm")) {
            return GeneratorConfig.getProjectResourcesRoute(GeneratorConfig.MODULE_STARTER) + "prod" +
                    File.separator + "bootstrap.yml";
        }
        if (template.contains("DubboDocConfig.java.vm")) {
            return GeneratorConfig.getProjectJavaRoute(GeneratorConfig.MODULE_CORE) + "config" + File.separator + "DubboDocConfig.java";
        }
        return null;
    }

    /**
     * 列名转换成Java属性名
     */
    private static String columnToJava(String columnName) {
        return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "");
    }
}
